package componentes;


import excessoes.LloginNuloException;
import excessoes.clienteException.ExecutarComandoLinuxException;
import excessoes.clienteException.ForaDoHorarioNavegacaoException;
import excessoes.clienteException.HoraInvalidaException;
import excessoes.clienteException.IpSemForwardException;
import excessoes.clienteException.MacSemForwardException;
import excessoes.clienteException.RecebeuLetrasException;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import principal.Main;
import threads.InsercaoBloqueado;
/**
 *
 * @author Wagner Tavares
 */
public class Cliente implements Serializable{
    private String ip, mac;
    private boolean bloqueado, ipEhReal, proxyTransparente;
    private int qntBytesAntigo;
    private boolean distincaoFDS;
    private Date horaInicial,horaFinal,horaInicialFDS,horaFinalFDS;
    private String ipDeMascaramento;
    private Servidor servidor;
    private ArrayList<String> retornoShell;
    private ArrayList<String> args = new ArrayList<String>();
    
    public Cliente (boolean bloqueado,String ip, String mac, Servidor servidor, boolean proxyTransparente, String horaInicial, String horaFinal, boolean distincaoFDS, String horaInicialFDS, String horaFinalFDS) throws HoraInvalidaException{
        this.ip = ip;
        this.mac = mac;
        this.servidor = servidor;
        this.proxyTransparente = proxyTransparente;
        String faixa=ip;
        for(int i = 0; i < 2; i++){
            faixa = faixa.substring(0, faixa.lastIndexOf("."));
        }
        String primeiroOctetoDoIp = faixa.substring(0, faixa.lastIndexOf("."));
        if( primeiroOctetoDoIp.equals("10") || primeiroOctetoDoIp.equals("172" ) || primeiroOctetoDoIp.equals("192") ){
            if( servidor!=null){
                if( servidor.getMascaramentos()!= null && !servidor.getMascaramentos().isEmpty() && servidor.getMascaramentos().containsKey(faixa))
                    ipDeMascaramento = servidor.getMascaramentos().get(faixa).getIp();
                else
                    ipDeMascaramento = servidor.getIpHost();
            } else {
                ipDeMascaramento = null;
            }
            ipEhReal = false;
        }else{
            ipDeMascaramento=null;
            ipEhReal = true;
        }
        this.bloqueado = bloqueado;
        qntBytesAntigo = 0;
        args.add(Linux.pathProg+File.separator+"comandos.sh ");
        for(String ethIn: servidor.getEthIn()){
            String temp=" "+
                    mac+" "+
                    ip+" "+
                    ipDeMascaramento+" "+
                    servidor.getPortaAutenticacaoWeb()+" "+
                    servidor.getPortaSquid()+" "+
                    servidor.getEthOut()+" "+
                    ethIn+" "+
                    ipEhReal+" "+
                    (servidor.getProxyTransparente()&&proxyTransparente);
            args.add(temp);   
        }
        String[] temp;
        if( horaFinal==null || horaFinal.isEmpty() )
            this.horaFinal = null;
        else{
            temp = horaFinal.split(":");
            this.horaFinal = new Date(2008,7,5,Integer.parseInt(temp[0]),Integer.parseInt(temp[1]),Integer.parseInt(temp[1]));
        }   
        if( horaFinalFDS==null || horaFinalFDS.isEmpty())
            this.horaFinalFDS =null;
        else{
            temp = horaFinalFDS.split(":");
            this.horaFinalFDS = new Date(2008,7,14,Integer.parseInt(temp[0]),Integer.parseInt(temp[1]),Integer.parseInt(temp[1]));
        }
        if( horaInicial==null || horaInicial.isEmpty())
            this.horaInicial = null;
        else{
            temp = horaInicial.split(":");
            this.horaInicial = new Date(2008,7,5,Integer.parseInt(temp[0]),Integer.parseInt(temp[1]),Integer.parseInt(temp[1]));
        }
        if( horaInicialFDS==null || horaInicialFDS.isEmpty())
            this.horaInicialFDS=null;
        else{
            temp = horaInicialFDS.split(":");
            this.horaInicialFDS = new Date(2008,7,11,Integer.parseInt(temp[0]),Integer.parseInt(temp[1]),Integer.parseInt(temp[1]));
        }
        this.distincaoFDS = distincaoFDS;                        
    }
    
    public synchronized void bloqueia(boolean geraLog) throws ExecutarComandoLinuxException, IpSemForwardException, MacSemForwardException, RecebeuLetrasException{
        boolean foiBloqueado = false;
        for(int i=0; i<(args.size()-1);i++){
            String cmd=args.get(0)+"-b"+args.get(i+1);
            int qntBytesAtual = 0;
            try {
                retornoShell = Linux.executa(cmd);
                qntBytesAtual = trataQntBytesTrafegados(retornoShell);
                if(qntBytesAtual==-1){
                    if(ipEhReal)
                        throw new IpSemForwardException("Cliente","bloqueia()",ip);
                    else
                        throw new MacSemForwardException("Cliente","bloqueia()",ip,mac);
                }else{
                    if(!geraLog)
                        qntBytesAntigo = qntBytesAtual;
                    bloqueado = true;
                    foiBloqueado=true;
                }
            }catch (ExecutarComandoLinuxException e) {
                e.setClasse("Cliente");
                e.setMetodo("bloqueia() , Linux."+e.getMetodo());
                e.setIp(ip);
                throw e;
            }catch (RecebeuLetrasException e) {
                 e.setMetodo("bloqueia() , "+e.getMetodo());
                 throw e;
            }
        }
        if(geraLog && foiBloqueado){
            Logger.getLogger(Main.class.getName()).log(Level.INFO,"Bloqueado! "+mac+"|"+ip);
            InsercaoBloqueado logBanco;
            try {
                logBanco = new InsercaoBloqueado(Main.config, ip);
                logBanco.start();
            } catch (LloginNuloException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
            
        }
    }
    public synchronized void tentaBloquear(boolean log) throws ExecutarComandoLinuxException, RecebeuLetrasException, IpSemForwardException, MacSemForwardException{
        int qntBytesAtual=0;
        String cmd=args.get(0)+"-c"+args.get(1);
        try{
            if(!bloqueado){
                qntBytesAtual = trataQntBytesTrafegados(Linux.executa(cmd));
                if(qntBytesAtual==-1){
                    qntBytesAntigo=0;
                    if(ipEhReal)
                        throw new IpSemForwardException("Cliente","tentaBloquear()",ip);
                    else
                        throw new MacSemForwardException("Cliente","tentaBloquear()",ip,mac);
                }else{
                    if(!verificaHorarioNavegacao() || qntBytesAtual == qntBytesAntigo )
                        if(bloqueado)
                            this.bloqueia(false);
                        else
                            this.bloqueia(log);
                    else
                        this.libera(false);
                }
            }else
                this.bloqueia(false);
        }catch (ExecutarComandoLinuxException e) {
            e.setClasse("Cliente");
            e.setMetodo("tentaBloquear() , Linux."+e.getMetodo());
            e.setIp(ip);
            throw e;
        }catch (RecebeuLetrasException e) {
            e.setMetodo("tentaBloquear() , "+e.getMetodo());
            throw e;
        }
    }
    public synchronized void libera(boolean geraLog) throws ExecutarComandoLinuxException, IpSemForwardException, MacSemForwardException, RecebeuLetrasException{
        boolean foiLiberado=false;
        for(int i=0; i<(args.size()-1);i++){
            String cmd=args.get(0)+"-l"+args.get(i+1);
            int qntBytesAtual;
            try {
                retornoShell = Linux.executa(cmd);
                qntBytesAtual = trataQntBytesTrafegados(retornoShell);
                if(qntBytesAtual==-1){
                    if(ipEhReal)
                        throw new IpSemForwardException("Cliente","bloqueia()",ip);
                    else
                        throw new MacSemForwardException("Cliente","bloqueia()",ip,mac);
                }else{
                    qntBytesAntigo = qntBytesAtual;
                    bloqueado = false;
                    foiLiberado=true;
                }
            }catch (ExecutarComandoLinuxException e) {
                e.setClasse("Cliente");
                e.setMetodo("libera() , Linux."+e.getMetodo());
                throw e;
            }catch (RecebeuLetrasException e) {
                 e.setMetodo("libera() , "+e.getMetodo());
                 throw e;
            }
        }if(geraLog && foiLiberado){
            Logger.getLogger(Main.class.getName()).log(Level.INFO,"Liberado! "+mac+"|"+ip);
        }
    }
    public void tentaLiberar() throws ExecutarComandoLinuxException, IpSemForwardException, MacSemForwardException, RecebeuLetrasException, ForaDoHorarioNavegacaoException{
        if(verificaHorarioNavegacao()){    
            libera(true);
        }else
            throw new ForaDoHorarioNavegacaoException("Cliente", "tentaLiberar()", ip);
    }
    public synchronized void aplicaBloqueadoOuLiberado() throws ExecutarComandoLinuxException, IpSemForwardException, MacSemForwardException, RecebeuLetrasException, ForaDoHorarioNavegacaoException{
        if(bloqueado)
            this.bloqueia(false);
        else
            this.libera(false);
    }
    public String getIp(){
        return ip;
    }
    public String getMac(){
        return mac;
    }
    public int getQntBytesAntigo(){
        return qntBytesAntigo;
    }
    public boolean getBloqueado(){
        return bloqueado;
    }
    public boolean getProxyTransparente(){
        return proxyTransparente;
    }
    public void setIp(String val){
        ip = val;
    }
    public void setMac(String val){
        mac = val;
    }
    public void setQntBytesAntigo(int val){
        qntBytesAntigo = val;
    }
    public void setBloqueado(boolean val){
        bloqueado = val;
    }
    private int trataQntBytesTrafegados(ArrayList<String> args) throws RecebeuLetrasException {
        int retorno=0;
        try{
            //if ( args.size() == 1){
                return Integer.parseInt(args.get(0));
            /*}else{
                for (String linha : args){
                    retorno+=Integer.parseInt(linha);
                }
            }*/
        }catch(NumberFormatException e){
            throw new RecebeuLetrasException("Cliente", "trataQntBytesTrafegados()", args, ip);
        }
        //return retorno;
    }
    private boolean verificaHorarioNavegacao(){
        Date agora = new Date();
        Date comparacao=null;
        if( distincaoFDS && (agora.getDay()==0 || agora.getDay()==1 || agora.getDay()==5 || agora.getDay()==6)){
            switch(agora.getDay()){
                case 5:{ // caso sexta
                    comparacao = new Date(2008,7,11,agora.getHours(),agora.getMinutes(),agora.getSeconds()); 
                    break;
                }
                case 6:{ // caso sábado
                    comparacao = new Date(2008,7,12,agora.getHours(),agora.getMinutes(),agora.getSeconds()); 
                    break;
                }
                case 0:{ //caso domingo
                    comparacao = new Date(2008,7,13,agora.getHours(),agora.getMinutes(),agora.getSeconds()); 
                    break;
                }
                case 1:{ //caso segunda
                    comparacao = new Date(2008,7,14,agora.getHours(),agora.getMinutes(),agora.getSeconds()); 
                    break;
                }
            }
            if(comparacao.compareTo(horaInicialFDS)>=0 && comparacao.compareTo(horaFinalFDS)<=0){
                return true;
            }
        }else{
            comparacao=new Date(2008,7,5,agora.getHours(),agora.getMinutes(),agora.getSeconds());
            if(comparacao.compareTo(horaInicial)>=0 && comparacao.compareTo(horaFinal)<=0){
                return true;
            }
        }
        return false;
    }
    public void exibir(){
        System.out.println("" +
                "IP: "+ip+"\n" +
                "MAC: "+mac+"\n" +
                "BLOQUEADO: "+bloqueado+"\n" +
                "IP REAL: "+ipEhReal+"\n" +
                "IP MASCARAMENTO: "+ipDeMascaramento+"\n"+
                "QNT BYTES ANTIGA: "+qntBytesAntigo+"\n" +
                "DISTINGUIR FDS: "+distincaoFDS+"\n" +
                "HORA INICIAL: "+horaInicial.toString()+"\n" +
                "HORA FINAL: "+horaFinal.toString()+"\n" +
                "HORA INICIAL FDS: "+horaInicialFDS.toString()+"\n" +
                "HORA FINAL FDS: "+horaFinalFDS.toString()+"\n");
    }
}
